package strategy;

import root.item.Item;
import root.loan.Borrow;
import root.loan.EmprestimoListener;
import root.user.User;
import exceptions.AbsentAtributException;
import exceptions.BorrowDoesNotExist;
import exceptions.HasAlreadyDoneException;
import exceptions.InvalidAtributException;
import exceptions.InvalidBorrowId;
import exceptions.InvalidDurationException;
import exceptions.InvalidMessage;
import exceptions.InvalidReceiver;
import exceptions.InvalidSubject;
import exceptions.IsNotOnwerException;
import exceptions.ItemDoesNotExist;
import exceptions.ItemHasAlreadyBorrowedException;
import exceptions.ItemRequestAlreadyExistsException;
import exceptions.LoanHasAlreadyBeenApprovedException;
import exceptions.PermissionDeniedException;
import exceptions.WithoutPermissionRequestLoanException;

public interface GerenciadorEmprestimoIF {
	
	
	public Borrow getBorrow(String id) throws BorrowDoesNotExist, InvalidBorrowId;
	
	public Borrow getRequestBorrow(String id) throws BorrowDoesNotExist, InvalidBorrowId;
	
	
	/**
	 * Verifica se uma indentificacao de resquisicao de emprestimo ou um emprestimo existe
	 * @param id Identificacao de uma requisicao de emprestimo ou de um emprestimo
	 * @return {@code true} Se a identificacao existir, {@code false} caso contrario
	 */
	public boolean hasBorrow(String id);
	
	/**
	 * O usuario {@code user} requisita o emprestimo do item de id 'itemId' por 'days' dias.
	 * @param user
	 * @param itemId
	 * @param days
	 * @return
	 * @throws ItemDoesNotExist
	 * @throws ItemRequestAlreadyExistsException
	 * @throws WithoutPermissionRequestLoanException
	 * @throws InvalidDurationException
	 * @throws AbsentAtributException 
	 * @throws InvalidAtributException 
	 * @throws InvalidReceiver 
	 * @throws InvalidSubject 
	 * @throws InvalidMessage 
	 * @throws IsNotOnwerException 
	 */
	public String borrowItem(Item item, int days, GerenciadorEmprestimoIF gEmprestimoDonoItem) throws ItemDoesNotExist, ItemRequestAlreadyExistsException, WithoutPermissionRequestLoanException, InvalidDurationException, InvalidAtributException, AbsentAtributException, InvalidMessage, InvalidSubject, InvalidReceiver, IsNotOnwerException;
	
	/**
	 * O usuario {@code user} indica devolucao do item emprestado ao dono e aguarda confirmacao
	 * @param user
	 * @param id Identificacao de emprestimo do item
	 * @throws PermissionDeniedException
	 * @throws HasAlreadyDoneException
	 * @throws BorrowDoesNotExist
	 * @throws InvalidBorrowId
	 */
	public void returnItem(String borrowId) throws PermissionDeniedException, HasAlreadyDoneException, BorrowDoesNotExist, InvalidBorrowId;
	
	/**
	 * O usuario {@code user}  requisita a devolucao do seu item de identificacao {@code id} 
	 * @param user
	 * @param id
	 * @throws BorrowDoesNotExist
	 * @throws InvalidBorrowId
	 * @throws HasAlreadyDoneException
	 * @throws PermissionDeniedException
	 * @throws ItemDoesNotExist
	 * @throws InvalidAtributException
	 * @throws AbsentAtributException
	 * @throws InvalidMessage
	 * @throws InvalidSubject
	 * @throws InvalidReceiver
	 */
	public void requestDevolution(String borrowId) throws BorrowDoesNotExist, InvalidBorrowId, HasAlreadyDoneException, PermissionDeniedException, ItemDoesNotExist, InvalidAtributException, AbsentAtributException, InvalidMessage, InvalidSubject, InvalidReceiver;
	
	/**
	 * O usuario {@code user} confirma a devolucao do item emprestado .
	 * @param user
	 * @param id Identificacao de emprestimo do item
	 * @throws PermissionDeniedException
	 * @throws HasAlreadyDoneException
	 * @throws ItemDoesNotExist
	 * @throws InvalidBorrowId
	 * @throws BorrowDoesNotExist
	 */
	public void completeLoan(String borrowId) throws PermissionDeniedException, HasAlreadyDoneException, ItemDoesNotExist, InvalidBorrowId, BorrowDoesNotExist;
	
	/**
	 *  O dono do item aprova uma requisicao de emprestimo de idntificacao {@code id}
	 * @param user Dono do item
	 * @param id
	 * @return
	 * @throws IsNotOnwerException
	 * @throws BorrowDoesNotExist
	 * @throws ItemDoesNotExist
	 * @throws LoanHasAlreadyBeenApprovedException
	 * @throws ItemHasAlreadyBorrowedException
	 * @throws InvalidBorrowId
	 * @throws PermissionDeniedException 
	 */
	public String approveLoan(String borrowId) throws IsNotOnwerException, BorrowDoesNotExist, ItemDoesNotExist, LoanHasAlreadyBeenApprovedException, ItemHasAlreadyBorrowedException, InvalidBorrowId, PermissionDeniedException;
	/**
	 * Retorna uma String contendo todos os emprestimos do usuario {@code user} sendo {@code "beneficiado"}, '{@code "emprestador"} ou ambos {@code "todos"}.
	 *  
	 * @param user
	 * @param atributo
	 * @return
	 * @throws InvalidAtributException
	 * @throws AbsentAtributException
	 * @throws ItemDoesNotExist
	 */
	public String getEmprestimos(String atributo) throws InvalidAtributException, AbsentAtributException, ItemDoesNotExist;
	
	/**
	 * Remove todas as requisicoes de emprestimo entre os usuarios {@code user1} e {@code user2}
	 * @param user1
	 * @param user2
	 */
	public void removesAllRequestsBetween(User user2);
	
	/**
	 * 
	 * @param user
	 * @param id
	 * @throws Exception Se o Usuario {@code user} nao participa nem como beneficiario nem como emprestador do emprestimo
	 */
	public void belongsLoan(String borrowId) throws Exception;
	
	/**
	 * Remove todas as requisicoes de emprestimo para o item de identificacao {@code id}
	 * @param idItem
	 */
	public void removesRequest(Item item);
	

	public void addListener(EmprestimoListener listener);
	
	public void addBorrowEmprestador(Borrow borrow) throws IsNotOnwerException;
	
}
